//
// Created by mmuee on 2023/8/4.
//

#ifndef PIULAB_STRING_HPP
#define PIULAB_STRING_HPP

#include <cstring>
#include <iostream>
#include <memory>
#include <mutex>
#include <sstream>
#include <filesystem>
#include <algorithm>

//using Separator = std::filesystem::path::preferred_separator;
const static char* Separator = "/";

inline std::string format_str()
{
    return {};
}

inline std::string format_str(const char* fmt, ...)
{
    va_list args1;
    va_list args2;
    va_start(args1, fmt);
    va_copy(args2, args1);
    auto size = vsnprintf(nullptr, 0, fmt, args1);
    std::string str;
    str.resize(size);
    va_end(args1);
    vsnprintf(str.data(), size + 1, fmt, args2);
    va_end(args2);
    return str;
}

inline std::string to_hex(const uint8_t* v, const size_t s, const std::string& spliter = "")
{
    std::stringstream ss;

    ss << std::hex << std::setfill('0');

    for (int i = 0; i < s; i++)
    {
        if (i > 0)
            ss << spliter;
        ss << std::hex << std::setw(2) << static_cast<int>(v[i]);
    }
    return ss.str();
}


inline std::vector<std::string> split(const std::string& line, const std::string& delim)
{
    size_t pstart = 0;
    size_t phit = 0;
    std::string sstr;
    size_t length = line.length();
    std::vector<std::string> vstr;
    vstr.clear();
    for (; pstart <= length;)
    {
        phit = line.find(delim, pstart);
        if (std::string::npos != phit)
        {
            /* find delim, get substr */
            sstr = line.substr(pstart, phit - pstart);
            vstr.push_back(sstr);
            pstart = phit + delim.size();
        }
        else
        {
            /* not find delim, append remaining str and break */
            vstr.push_back(line.substr(pstart));
            break;
        }
    }
    return vstr;
}

inline size_t split(const std::string& line, const std::string& delim, std::vector<std::string>& vstr)
{
    size_t pstart = 0;
    size_t phit = 0;
    std::string sstr;
    size_t length = line.length();
    vstr.clear();
    for (; pstart <= length;)
    {
        phit = line.find(delim, pstart);
        if (std::string::npos != phit)
        {
            /* find delim, get substr */
            sstr = line.substr(pstart, phit - pstart);
            vstr.push_back(sstr);
            pstart = phit + delim.size();
        }
        else
        {
            /* not find delim, append remaining str and break */
            vstr.push_back(line.substr(pstart));
            break;
        }
    }
    return vstr.size();
}

template<class T>
std::string join(T& val, std::string delim)
{
    std::string str;
    typename T::iterator it;
    const typename T::iterator itlast = val.end() - 1;
    for (it = val.begin(); it != val.end(); it++)
    {
        str += *it;
        if (it != itlast)
        {
            str += delim;
        }
    }
    return str;
}

// trim from start (in place)
inline void ltrim(std::string& s)
{
    s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
}

// trim from end (in place)
inline void rtrim(std::string& s)
{
    s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
}

inline std::string subreplace(const std::string& src, const std::string& old, const std::string& new_str)
{
    std::string dst_str = src;
    std::string::size_type pos = 0;
    while ((pos = dst_str.find(old)) != std::string::npos) //替换所有指定子串
    {
        dst_str.replace(pos, old.length(), new_str);
    }
    return dst_str;
}

#endif //PIULAB_STRING_HPP
